home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
331_01
/
swap.c
< prev
next >
Wrap
Text File
|
1990-06-12
|
10KB
|
357 lines
/*
HEADER: CUG199.09;
TITLE: GED (nee QED) screen editor -- part 9;
DATE: 10/10/86;
DESCRIPTION: "Virtual memory manager for GED editor. Eg. swapout,
pageout.";
KEYWORDS: text storage, memory management, virtual storage, paging;
SYSTEM: MS-DOS;
FILENAME: GED9.C;
AUTHORS: G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
COMPILERS: DeSmet C;
*/
/*
e/qed/ged screen editor
(C) G. Nigel Gilbert, MICROLOGY, 1981
August-December 1981
Modified: Aug-Dec 1984: BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
March 1985: BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
May 1986: converted to ged - Mel Tearle
FILE: ged9.c
FUNCTIONS: initvm, freememslot, swapout, writepage,
swappin, readpage, fatalerror
PURPOSE: manages virtual memory
*/
#include <stdio.h>
#include "ged.h"
int allo;
/* Initialize virtual memory system. There are MAXSLOTS pages. The data in a given
page may be either in RAM or in a temporary disc file. The most recently
used data is kept in RAM. There are up to RAMSLOTS of pages in RAM.
If virtslot[page] is positive then the value is the slot number in RAM
which contains the text for that page. If negative then the disc slot
number is -(virtslot[page] + 1).
Selective use is made of 32-bit pointers. Most of the program uses 16-bit
pointers and would be difficult and inefficient to convert to a large
data model. Pointer arithmetic on far pointers cannot cross a 64k boundary.
Huge pointer calculations can cross these boundaries. The use of far and
huge pointers is controlled by the preprocessor directives in ged.h.
If the page size is evenly divisible into 64 k then a page will never
span a 64 k boundary and far pointers can be used in time critical functions.
The far pointer arithmetic is significantly faster for far pointers and
they are used in this version. There are also places where huge
pointer arithmetic must be used in order to obtain correct carry
propogation.
*/
initvm()
{
int slot;
unsigned int size;
static unsigned long int lsize;
static char HUGE * hptr = 0L;
char HUGE * cdecl hptr1;
int i;
long int ll;
char *malloc();
char *ptr;
char HUGE * malloc2();
char buf[40];
if (sizeof(*tp) != sizeof(long))
cerr(92); /* see comments in deltp() */
/* fullmem set by -M load time option */
if (hptr == 0L) {
lsize = (long) fullmem*1024L;
hptr = malloc2(&lsize); /* adjusts lsize downward */
}
hptr1 = hptr;
slotsinmem = lsize/PAGESIZE;
if ( slotsinmem < 3 ) {
error1( "Can't allocate enough memory" );
xit();
}
allo = lsize/1024L;
for (slot = 0; slot < slotsinmem; slot++) {
usage[slot] = 0;
auxloc[slot] = 0;
slotaddr[slot] = hptr1;
hptr1 += PAGESIZE;
}
for (i = 0; i < MAXSLOTS; i++) {
virtslot[i] = 0;
dskslots[i] = 0;
}
clock = 1;
/* reserve slot 0 for an array of tp structures. Additional slots
* will be taken later for tp if needed.
*/
tp = (struct addr HUGE *)slotaddr[0];
tpslots = 1;
usage[tpslots-1] = -1;
/* assign first page for line injection. */
newpage = 0;
virtslot[newpage] = freememslot();
allocp = 0;
usage[virtslot[newpage]] = MAXINT;
/* paging file not yet created */
pagefd = NOFILE;
return;
}
/* Returns the number of a free memory slot, possibly by swapping out
the least recently used page currently in memory. If that page is
already on disc then the RAM slot is immediately reused.
On the initial read, text is stored starting at the top of allocated
memory and working downward. The tp array works upward from low memory.
The portion used by tp must be contiguous. newpage is not swaped out.
*/
int freememslot()
{
int use, u;
int i, slot, nclk;
nclk = 1;
use = MAXINT;
slot = slotsinmem-1;
for ( i = slotsinmem-1; (use != 0) && (i >= tpslots); i-- ) {
if ( ( u = usage[i] ) < use ) {
use = u;
slot = i;
}
}
if ( use > 0 ) {
swapout( slot ); /* no free slots. make one */
}
auxloc[slot] = 0; /* RAM slot has no disc association */
if (!goteof)
usage[slot] = clock++;
return slot;
}
/* swaps page currently in memory at 'slot' to disk,
* updating virtslot to show new location
*/
swapout(slot)
int slot;
{
int pg;
/* find page number for ram data at 'slot' */
for ( pg = 0; (virtslot[pg] != slot) && (pg < MAXSLOTS); pg++ )
;
if(pg==MAXSLOTS)
cerr(90); /* memory is probably clobbered */
if (auxloc[slot] == 0) {
virtslot[pg] = -writepage( slot ) - 1; /* update virtslot with disk slot written to */
}
else {
virtslot[pg] = auxloc[slot]; /* page already exists on disc */
auxloc[slot] = 0; /* RAM slot will lose its disc association with this record */
}
usage[slot] = 0; /* the ram slot is free */
return;
}
/* Writes page currently in memory at 'slot' to disk.
* Returns disk slot where written. Locations near the beginning
* of the file are used when available to miminize total file size.
*/
writepage(slot)
int slot;
{
int i;
unsigned loc;
long int sekbytes;
long int lseek1();
long int dbuf[PAGESIZE/sizeof(long)];
long int *pt1;
long int FAR *pt2;
if ( pagefd == NOFILE ) { /* haven't opened paging file yet */
if ( (pagefd = creatb(pagingfile)) == FAIL )
fatalerror( " Can't create a buffer file" );
for ( loc = 0; loc < MAXSLOTS; loc++ )
dskslots[loc] = 0;
}
for ( loc = 0; dskslots[loc] != 0; loc++ ) /* find a free slot */
;
if (loc >= MAXSLOTS)
cerr(93); /* table corrupt */
sekbytes = (long) loc*PAGESIZE;
if ( lseek1( pagefd, sekbytes) == -1L )
fatalerror(" Bad seek in writing buffer ");
/* move far data to near data */
pt2 = (long int FAR *) slotaddr[slot];
pt1 = &dbuf[0];
for (i = 1; i <= PAGESIZE/sizeof(long); i++)
*pt1++ = *pt2++;
if ( write( pagefd, dbuf, PAGESIZE ) == FAIL )
fatalerror(" Can't write to buffer - disk full " );
dskslots[loc] = 1;
usage[slot] = 0;
return loc;
}
/* get 'page', currently on disk,
* into memory and return slot where placed
* the disc location is saved in auxloc in case the page needs to be
* rolled out again without change.
*
* The priority is set to 1 when read. If read for a global string search
* the priority stays at the lowest priority and the same memory slot will
* be used for the next page. The established page priority is therefore
* mostly unaffected by global searches. If loaded for gettext() the
* priority will immediately be raised to 'clock' and the page will
* usually stay resident for a long time.
*/
swappin(page)
int page;
{
int slot, dslot;
int i;
if(virtslot[page] >= 0)
cerr(91); /* table corrupt */
slot = freememslot();
readpage( slot, -1 -virtslot[page] );
usage[slot] = 1;
auxloc[slot] = virtslot[page]; /* remember where it came from */
virtslot[page] = slot;
return slot;
}
/* read a page from disk into
* memory at 'memsl'
*/
readpage(memsl,dskslot)
int memsl, dskslot;
{
long sekbytes;
int i;
long int *pt1;
long int FAR *pt2;
long int dbuf[PAGESIZE/sizeof(long)];
char buf[80];
long int lseek1();
sekbytes = (long) dskslot*PAGESIZE;
if ( lseek1( pagefd, sekbytes ) == -1L )
fatalerror(" Bad seek in reading buffer ");
i=read( pagefd, dbuf, PAGESIZE );
if ( i != PAGESIZE )
fatalerror(" Can't read disc